﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Thrift.Utility
{
    public static class CacheFactory
    {
        private static Dictionary<string, ICache> s_CacheProviders = new Dictionary<string, ICache>();
        private static object s_SyncObj = new object();
        public static ICache GetInstance()
        {
            return CacheFactory.GetInstance(null);
        }
        public static ICache GetInstance(string name)
        {
            CacheSetting setting = CacheSection.GetSetting();
            if (string.IsNullOrWhiteSpace(name))
            {
                name = setting.DefaultCacheName;
            }
            if (string.IsNullOrWhiteSpace(name))
            {
                throw new ConfigurationErrorsException("The default cache name is not configured in config file.");
            }
            if (CacheFactory.s_CacheProviders.ContainsKey(name))
            {
                return CacheFactory.s_CacheProviders[name];
            }
            else
            {
                lock (CacheFactory.s_SyncObj)
                {
                    if (CacheFactory.s_CacheProviders.ContainsKey(name))
                    {
                        return CacheFactory.s_CacheProviders[name];
                    }
                    else
                    {
                        if (!setting.ContainsKey(name))
                        {
                            throw new ConfigurationErrorsException(string.Format("The cache named \"{0}\" is not be found in config file.", name));
                        }
                        CacheItemConfig cacheItemConfig = setting[name];
                        if (string.IsNullOrWhiteSpace(cacheItemConfig.Type))
                        {
                            throw new ConfigurationErrorsException(string.Format("The type of cache \"{0}\" cannot be empty.",name));
                        }
                        Type type = Type.GetType(cacheItemConfig.Type, true);
                        if (!typeof(ICache).IsAssignableFrom(type))
                        {
                            throw new ConfigurationErrorsException(string.Format("The type \"{0}\" of cache \"{1}\" dosen't implement the interface \"{2}\".", type.AssemblyQualifiedName, name, typeof(ICache).AssemblyQualifiedName));
                        }
                        ICache cache = (ICache)Activator.CreateInstance(type);
                        cache.InitFromConfig(name, cacheItemConfig.Parameters);
                        CacheFactory.s_CacheProviders.Add(name, cache);
                        return cache;
                    }
                }
            }
        }
    }
}
